package cn.funeralobjects.ams.web.service;

import cn.funeralobjects.ams.web.api.ProductApi;
import cn.funeralobjects.ams.web.api.ProductApiApi;
import cn.funeralobjects.ams.web.model.VProduct;
import cn.funeralobjects.ams.web.model.VProductApi;
import cn.funeralobjects.ams.web.utils.ApiUtils;
import cn.funeralobjects.util.annotation.ArgHasLength;
import cn.funeralobjects.util.annotation.AssertArg;
import cn.funeralobjects.utils.aliyun.core.model.AliyunAction;
import cn.funeralobjects.utils.aliyun.core.model.AliyunProduct;
import org.slf4j.Logger;
import org.springframework.beans.factory.InitializingBean;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 阿里云模块初始化的基本类
 *
 * @author FuneralObjects
 * Create date: 2020/6/2 9:29 AM
 */
public abstract class BaseAliyunMouduleRegister implements InitializingBean {


    /**
     * ProductApi
     *
     * @return ProductApi
     */
    protected abstract ProductApi getProductApi();

    /**
     * ProductApiApi
     *
     * @return ProductApiApi
     */
    protected abstract ProductApiApi getProductApiApi();

    /**
     * 获取需要注册的产品对象
     *
     * @return list[product]
     */
    protected abstract List<AliyunProduct> getRegisteredProducts();

    /**
     * 获取需要注册的产品的api
     *
     * @return product.code -- action
     */
    protected abstract ConcurrentMap<String, List<AliyunAction>> getRegisteredProductApis();

    /**
     * 获取日志对象
     *
     * @return Logger
     */
    protected abstract Logger getLogger();

    protected ConcurrentMap<String, VProduct> productMap = new ConcurrentHashMap<>(getRegisteredProducts().size());
    protected ConcurrentMap<String, VProductApi> productApiMap = new ConcurrentHashMap<>(Long.valueOf(getRegisteredProductApis().values().stream().mapToLong(Collection::size).sum()).intValue());

    @Override
    public void afterPropertiesSet() throws Exception {

        getRegisteredProducts().stream()
                .forEach(product -> {
                    ApiUtils.addProductIfNotExists(product, getProductApi()).subscribe(vProduct -> {
                        productMap.put(vProduct.getCode(), vProduct);
                        getLogger().info("The Product[{}-{}] registered!", product.code(), product.description());
                        getRegisteredProductApis().getOrDefault(vProduct.getCode(), Collections.emptyList())
                                .forEach(aAction -> ApiUtils.addProductApiIfNotExists(aAction, getProductApiApi(), vProduct.getId())
                                        .subscribe(api -> {
                                            getLogger().info("The ProductApi[{}-{}] in Product[{}] registered!", api.getAction(), api.getVersion(), vProduct.getCode());
                                            productApiMap.put(getKey(aAction), api);
                                        }));
                    });
                });


    }

    protected String getKey(AliyunAction aliyunAction) {
        return aliyunAction.getAction() + "-" + aliyunAction.getVersion();
    }

    @AssertArg
    public VProduct getProduct(@ArgHasLength String code) {
        return productMap.getOrDefault(code, null);
    }

    @AssertArg
    public VProductApi getProductApiId(@ArgHasLength String action, @ArgHasLength String version) {
        return productApiMap.getOrDefault(action + "-" + version, null);
    }
}
